package cn.jiaqiang.chatgpt.data.domain.order.service;


import cn.jiaqiang.chatgpt.data.domain.order.model.entity.*;
import cn.jiaqiang.chatgpt.data.domain.order.model.valobj.PayStatusVO;
import cn.jiaqiang.chatgpt.data.domain.order.repository.IOrderRepository;
import cn.jiaqiang.chatgpt.data.domain.snow.SnowflakeIdGenerator;
import cn.jiaqiang.chatgpt.data.types.common.Constants;
import cn.jiaqiang.chatgpt.data.types.exception.ChatGPTException;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;

/**
 * @description 抽象订单服务
 */
@Slf4j
@Service
public abstract class AbstractOrderService implements IOrderService {

    @Resource
    protected SnowflakeIdGenerator snowflakeIdGenerator;

    @Resource
    protected IOrderRepository orderRepository;

    @Override
    @Transactional(rollbackFor = Exception.class, timeout = 350, propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
    public PayOrderEntity createOrder(ShopCartEntity shopCartEntity) {
        try {

            // -1 获取当前代理对象
            AbstractOrderService proxy = (AbstractOrderService) AopContext.currentProxy();

            // 0. 拿到openid和商品id
            String openid = shopCartEntity.getOpenid();
            Integer productId = shopCartEntity.getProductId();

            // 1. 查询有效的未支付订单，如果存在直接返回 微信支付 Native CodeUrl
                                                    /** <!-- queryUnpaidOrder 查询未支付订单 --> */
            UnpaidOrderEntity unpaidOrderEntity = orderRepository.queryUnpaidOrder(shopCartEntity);
            if (null != unpaidOrderEntity && PayStatusVO.WAIT.equals(unpaidOrderEntity.getPayStatus()) && null != unpaidOrderEntity.getPayUrl()) {
                log.info("创建订单-存在，已生成微信支付，返回 openid: {} orderId: {} payUrl: {}", openid, unpaidOrderEntity.getOrderId(), unpaidOrderEntity.getPayUrl());
                return PayOrderEntity.builder().openid(openid).orderId(unpaidOrderEntity.getOrderId()).payUrl(unpaidOrderEntity.getPayUrl()).payStatus(unpaidOrderEntity.getPayStatus()).build();
            } else if (null != unpaidOrderEntity && null == unpaidOrderEntity.getPayUrl()) {
                log.info("创建订单-存在，未生成微信支付 openid: {} orderId: {}", openid, unpaidOrderEntity.getOrderId());

                PayOrderEntity payOrderEntity = proxy.doPersonalPrepayOrder(openid, unpaidOrderEntity.getOrderId(), unpaidOrderEntity.getProductName(), unpaidOrderEntity.getTotalAmount().toString());
                if (payOrderEntity == null) {
                    log.error("创建订单-失败, 支付单生成失败");
                    throw new RuntimeException("创建订单-失败, 支付单生成失败");
                }
                log.info("创建订单-完成，生成支付单。openid: {} orderId: {} payUrl: {}", openid, payOrderEntity.getOrderId(), payOrderEntity.getPayUrl());
                return payOrderEntity;
            }
            log.info("创建订单-不存在有效的未支付订单，开始创建点单，返回 openid: {}", openid);
            // 2. 商品查询
            ProductEntity productEntity = orderRepository.queryProduct(productId);
            log.info("商品: {}", productEntity.toString());
            if (!productEntity.isAvailable()) {
                throw new ChatGPTException(Constants.ResponseCode.ORDER_PRODUCT_ERR.getCode(), Constants.ResponseCode.ORDER_PRODUCT_ERR.getInfo());
            }

            // 3. 保存订单
            OrderEntity orderEntity = proxy.doSaveOrder(openid, productEntity);
            log.info("创建订单-订单保存成功, 未生成微信支付, 开始生成支付单，返回 openid: {} orderId: {}", openid, orderEntity.getOrderId());

            // 4. 创建支付单
            PayOrderEntity payOrderEntity = proxy.doPersonalPrepayOrder(openid, orderEntity.getOrderId(), productEntity.getProductName(), orderEntity.getTotalAmount().toString());
            if (payOrderEntity == null) {
                log.error("创建订单-失败, 支付单生成失败...");
                throw new RuntimeException("创建订单-失败, 支付单生成失败...");
            }
            log.info("创建订单-完成，生成支付单。openid: {} orderId: {} payUrl: {}", openid, orderEntity.getOrderId(), payOrderEntity.getPayUrl());

            return payOrderEntity;
        } catch (Exception e) {
            log.error("创建订单出错: ", e);
            log.error("创建订单-出错，已生成微信支付，返回 openid: {} productId: {}", shopCartEntity.getOpenid(), shopCartEntity.getProductId());
            return null;
        }
    }

    protected abstract OrderEntity doSaveOrder(String openid, ProductEntity productEntity);

    protected abstract PayOrderEntity doPrepayOrder(String openid, String orderId, String productName, BigDecimal amountTotal);

    protected abstract PayOrderEntity doPersonalPrepayOrder(String openid, String orderId, String productName, String amountTotal);
}
